-- @Author: baidwwy
-- @Date:   2018-04-10 22:51:52
-- @Last Modified by:   baidwwy
-- @Last Modified time: 2018-08-29 20:25:07
引擎 = {}
--setmetatable(gge, {__index=引擎})
local _GGE = require("gge_base")()
local _XY,_KEY
local _更新函数,_渲染函数
local _更改标题,_是否退出,_更改宽高
--==============================================================
if not __gge.isdebug then
    local 脚本 =
    [[
        文字 = require("gge文字类")("C:/Windows/Fonts/simsun.ttc",16)
        文字:置行宽(%d)
        文字2 = require("gge文字类")("C:/Windows/Fonts/simsun.ttc",150,false,false,true)
        文字2:置颜色(0x30000000)
        function 引擎:渲染函数()
            引擎.渲染开始()
            引擎.渲染清除(0xFF808080)
                文字2:显示(%d,%d,"GGELUA")--恳请保留
                文字:显示(10,10,"游戏崩溃了,请截图报告作者;并详细说明崩溃前的操作过程。\n")
                文字:显示(10,30,错误信息)
            引擎.渲染结束()
        end
    ]]
    local 已显示
    __gge.traceback = function (msg)
        if not 已显示 then
            已显示 = true
            if 引擎.已运行 then
                _更新函数 = nil
                错误信息 = debug.traceback(msg,2)
                loadstring(string.format(脚本, 引擎.宽度-20,(引擎.宽度-450)/2,引擎.高度-300))()
            else
                __gge.messagebox(tostring(msg),"致命的错误",16)
                _更新函数,_渲染函数 = nil,nil
                _是否退出 = true
            end
        end
    end
end
--==============================================================
local function __Exit()
    if not 引擎.退出函数 or __gge.xpcall(引擎.退出函数,引擎) then
        _GGE:System_Stop()
        for k,v in pairs(引擎.线程列表) do
            v:停止()
        end
        _是否退出 = true
    end
    return false
end
--==============================================================
local _更新列表   = setmetatable({}, {__mode = 'v'})
local _渲染列表   = setmetatable({}, {__mode = 'v'})
local _尾更新列表 = setmetatable({}, {__mode = 'v'})
local function __FrameLoop(dt,x,y)
    if not _是否退出 then
        _XY:更新(x,y)
        _KEY = _GGE:Input_GetKey()
        if(_KEY>0 and 引擎.按键函数)then
            if __gge.xpcall(引擎.按键函数,引擎,_GGE:Input_GetKeyName(_KEY),_KEY) then
                __Exit()
                return true
            end
        end
        for i,v in ipairs(_更新列表) do
            __gge.xpcall(v.更新,v,dt,x,y,_XY)
        end
        if(_更新函数)then
            if __gge.xpcall(_更新函数,引擎,dt,x,y,_XY) then
                return true
            end
        end
        if(_渲染函数)then
            if __gge.xpcall(_渲染函数,引擎,x,y,_XY) then
                return true
            end
        end
        for i,v in ipairs(_尾更新列表) do
            __gge.xpcall(v.更新,v,dt,x,y,_XY)
        end
        if _更改标题 then
            _GGE:System_SetStateCHAR(0,_更改标题)
            引擎.标题,_更改标题 = _更改标题,nil
        end
        if _更改宽高 then
            _GGE:System_SetStateINT(3,引擎.宽度)
            _GGE:System_SetStateINT(4,引擎.高度)
            _更改宽高 = nil
        end
    else
        for k,v in pairs(引擎.线程列表) do
            if not v:是否停止() then
                return false
            end
        end
        return true
    end
    return false
end
--==============================================================
local function __FocusLost()
    if 引擎.失去焦点 then
        return __gge.xpcall(引擎.失去焦点,引擎)
    end
    return false
end
--==============================================================
local function __FocusGain()
    if 引擎.获得焦点 then
        return __gge.xpcall(引擎.获得焦点,引擎)
    end
    return false
end
--==============================================================
ffi.cdef[[
    typedef struct
    {
        long   styleOld;
        long   styleNew;
    } STYLESTRUCT
]]

-- 引擎.无边框 = true
-- function 测试(hwnd)
--  local ffi = require( "ffi" )

--  ffi.cdef[[
--  typedef struct {
--      unsigned long dwSize;
--      unsigned long dwStyle;
--      unsigned long dwCount;
--      unsigned long dwSelection;
--      unsigned long dwPageStart;
--      unsigned long dwPageSize;
--      unsigned long dwOffset[1];
--  } LPCANDIDATELIST;
--  void*   malloc(int);
--  void    free(void*);
--  int     ImmGetContext(int);
--  bool    ImmReleaseContext(int ,int);
--  int     ImmGetCandidateListA(int,int,void*,int);
--  ]]
--  local imm32 = ffi.load("imm32.dll")
--  local hIMC  = imm32.ImmGetContext(hwnd)
--  local len = imm32.ImmGetCandidateListA(hIMC,0,nil,0)
--  if len>28 then
--      local pList = ffi.new('char[?]',len)
--      imm32.ImmGetCandidateListA(hIMC,0,pList,len)
--      local List = ffi.cast("LPCANDIDATELIST*",pList)
--      for i=0,List.dwCount-1 do
--          print(ffi.string(pList+List.dwOffset[i]))
--      end
--  end
--  imm32.ImmReleaseContext(hwnd,hIMC)
-- end
local _鼠标常量 = {
    [513] = '左键按下';[514] = '左键弹起';[515] = '左键双击';
    [516] = '右键按下';[517] = '右键弹起';[518] = '右键双击';
    [519] = '中键按下';[520] = '中键弹起';[521] = '中键双击';
    [522] = '鼠标滚动';
}
local _消息列表 = setmetatable({}, {__mode='v'})
local _鼠标列表 = setmetatable({}, {__mode='v'})
local _键盘列表 = setmetatable({}, {__mode='v'})
local function _发送事件(列表,名称,...)
    for i,v in ipairs(列表) do
        __gge.xpcall(v[名称],v,...)
    end
end
local function __Message(HWND,UMSG,WPARAM,LPARAM)
    if UMSG == 0x007C and WPARAM == -16 and 引擎.无边框 then--WM_STYLECHANGING,GWL_STYLE
        local StyleStruct = ffi.cast("STYLESTRUCT*",LPARAM)
        StyleStruct.styleNew = bit.bor(0x80000000,0x10000000)--WS_POPUP,WS_VISIBLE
        --StyleStruct.styleNew = 348389376--删除窗口控制按钮和图标
        ffi.C.SetWindowLongA(HWND,-8,0x00000080)--隐藏任务栏
        引擎.无边框 = false
        print(123)
    end
    if UMSG > 512 and UMSG < 523 then
        _发送事件(_鼠标列表,'鼠标消息',UMSG,WPARAM,LPARAM)
        if 引擎.鼠标函数 then __gge.xpcall(引擎.鼠标函数,引擎,_鼠标常量[UMSG],WPARAM,LPARAM)end
        return true
    end
    if(UMSG==646)then--WM_IME_CHAR
        if WPARAM<=127 then
            __Message(HWND,258,WPARAM,LPARAM)
        else
            _发送事件(_键盘列表,'键盘消息',UMSG,string.char(bit.rshift(WPARAM,8),bit.band(WPARAM,255)),WPARAM)
            if 引擎.输入函数 then __gge.xpcall(引擎.输入函数,引擎,UMSG,string.char(bit.rshift(WPARAM,8),bit.band(WPARAM,255)),WPARAM)end
        end
        return true
    elseif UMSG == 258 then--WM_CHAR
        _发送事件(_键盘列表,'键盘消息',UMSG,string.char(WPARAM),WPARAM)
        if 引擎.输入函数 then __gge.xpcall(引擎.输入函数,引擎,UMSG,string.char(WPARAM),WPARAM) end
        return true
    elseif UMSG == 256 then--WM_KEYDOWN
        --print(UMSG,WPARAM,LPARAM)
    end
    if UMSG ==260 or UMSG ==261 or UMSG ==262 then --ALT
        return true
    end
    _发送事件(_消息列表,'窗口消息',UMSG,WPARAM,LPARAM)
    if 引擎.消息函数 then __gge.xpcall(引擎.消息函数,引擎,UMSG,WPARAM,LPARAM)end
    -- if UMSG == 0x010F then--输入法候选

    -- elseif UMSG == 0x0282 then
    --  if WPARAM == 0x0005 then --or WPARAM == 0x0009 or WPARAM == 0x0003 or WPARAM == 0x0004 then
    --      --测试(HWND)
    --  end
    -- end
    return false
end

--<<=========================================================================================>>--
--引擎
--<<=========================================================================================>>--
--@说明 创建引擎

local self = 引擎

function 引擎.创建(参数)
    if not self.已运行 then
        参数 = 参数 or {}

        self.标题     = 参数.标题 or "Galaxy2D Game Engine"
        self.原始标题 = self.标题
        self.宽度     = 参数.宽度 or 800
        self.高度     = 参数.高度 or 600
        self.宽度2    = self.宽度/2
        self.高度2    = self.高度/2
        self.帧率     = 参数.帧率 or 60
        self.全屏     = 参数.全屏
        self.纹理列表 = setmetatable({}, {__mode='kv'})
        self.精灵列表 = setmetatable({}, {__mode='kv'})
        self.动画列表 = setmetatable({}, {__mode='kv'})
        self.文字列表 = setmetatable({}, {__mode='kv'})
        self.音效列表 = setmetatable({}, {__mode='kv'})
        self.线程列表 = setmetatable({}, {__mode='kv'})
        _XY   = require("gge坐标类")()
        if _GGE:Engine_Create() then

            _GGE:System_SetStateCHAR(0,self.标题)
            _GGE:System_SetStateCHAR(1,参数.日志 or "./GGELUA.log")

            _GGE:System_SetStateINT(0,104)--图标号
            _GGE:System_SetStateINT(1,self.帧率)
            _GGE:System_SetStateINT(2,self.全屏 and 1 or 0)
            _GGE:System_SetStateINT(3,self.宽度)
            _GGE:System_SetStateINT(4,self.高度)
            --_GGE:System_SetStateINT(5,32)

            _GGE:System_SetStateBOOL(0,参数.鼠标)      --是否隐藏系统鼠标，可在运行时更改，默认:true
            _GGE:System_SetStateBOOL(1,__gge.isdebug)  --是否开启调试信息，可在运行时更改，默认:true
            _GGE:System_SetStateBOOL(2,参数.挂起)      --非激活状态时是否挂起，默认:false
            --_GGE:System_SetStateBOOL(3,false)          --是否开启Z缓冲，可在运行时更改，默认:false
            --_GGE:System_SetStateBOOL(4,false)          --是否开启垂直同步，可在运行时更改，默认:false
            --_GGE:System_SetStateBOOL(5,false)          --强制开启纹理过滤，可在运行时更改，默认:false
            _GGE:System_SetStateBOOL(6,true)           --是否保持浮点精度，用于解决D3D自动修改浮点精度导致的一些问题，默认:false

            _GGE:System_SetStateFUN(0,__FrameLoop)
            _GGE:System_SetStateFUN(1,__Exit)
            _GGE:System_SetStateFUN(2,__FocusLost)
            _GGE:System_SetStateFUN(3,__FocusGain)
            _GGE:System_SetStateFUN(4,__Message)
            self.已运行 = _GGE:System_Initiate()
            _GGE:System_Log(__gge.version)
            _GGE:System_Log
[[
--==================================================--
绑定作者：baidwwy
主页地址: http://www.ggelua.com
电子邮箱: baidwwy@vip.qq.com
支 付 宝: baidwwy@vip.qq.com
--==================================================--
]]
        ffi.C.SetDllDirectoryA(nil)
        end
        if self.已运行 and __gge.isdebug then
            -- print(">",
            --     "纹理最大尺寸",_GGE:System_GetStateINT(5),
            --     "纹理最大单元数",_GGE:System_GetStateINT(7),
            --     "PixelShader版本",_GGE:System_GetStateINT(6)
            --     )
            print(">",self.标题,self.宽度,self.高度,self.帧率)
        end
        print("-----------------------------------------------------------------")
        if self.已运行 then
            if self.创建完成 then self:创建完成() end
        else
            __gge.messagebox("请尝试安装DirectX驱动程序。","错误",48)
            os.exit()
        end
    end

    return self
end
--============================================================================================
--统计数量
--============================================================================================
    local function _统计数量(列表)
        local n = 0
        for k,v in pairs(列表) do
            n=n+1
        end
        return n
    end
    function 引擎.取纹理数()
        return _统计数量(self.纹理列表)
    end
    function 引擎.取精灵数()
        return _统计数量(self.精灵列表)
    end
    function 引擎.取动画数()
        return _统计数量(self.动画列表)
    end
    function 引擎.取文字数()
        return _统计数量(self.文字列表)
    end
--============================================================================================
function 引擎.加入更新对象(v)
    if type(v) == 'table' and type(v.更新) == 'function' then
        table.insert(_更新列表,v)
        return v
    end
end
function 引擎.加入尾更新对象(v)
    if type(v) == 'table' and type(v.更新) == 'function' then
        table.insert(_尾更新列表,v)
        return v
    end
end
function 引擎.加入渲染对象(v)
    if type(v) == 'table' and type(v.显示) == 'function' then
        table.insert(_渲染列表,v)
        return v
    end
end
function 引擎.加入消息回调(v)
    if type(v) == 'table' and type(v.窗口消息) == 'function' then
        table.insert(_消息列表,v)
        return v
    end
end
function 引擎.加入鼠标回调(v)
    if type(v) == 'table' and type(v.鼠标消息) == 'function' then
        table.insert(_鼠标列表,v)
        return v
    end
end
function 引擎.加入键盘回调(v)
    if type(v) == 'table' and type(v.键盘消息) == 'function' then
        table.insert(_键盘列表,v)
        return v
    end
end
--============================================================================================
--系统
--============================================================================================
function 引擎.关闭()
    _GGE:System_Stop()
    for k,v in pairs(引擎.线程列表) do
        v:停止()
    end
    _是否退出 = true
end
function 引擎.是否运行()
    return self.已运行
end
function 引擎.是否全屏()
    return self.全屏
end
function 引擎.置标题(v)
    _更改标题 = v
end
--@说明 切换窗口为全屏，再次调用返回窗口
--@参数 bool
function 引擎.置全屏()
    self.全屏 = not self.全屏
    _GGE:System_SetStateINT(2,self.全屏 and 1 or 0)
    return self.全屏
end

function 引擎.置宽高(k,g)
    self.宽度  = k or 800
    self.高度  = g or 600
    self.宽度2 = self.宽度/2
    self.高度2 = self.高度/2
    _更改宽高  = true
end

--@说明 切换窗口为无框模式，再次调用返回正常
--@参数 bool
function 引擎.置无框()
    --_GGE:System_SetStateBOOL(0,v)
end
--@说明 强制垂直同步
--@参数 bool
function 引擎.垂直同步(v)
    _GGE:System_SetStateBOOL(4,v)
    return 引擎
end
--@说明 修改窗口图标
--@参数 exe资源号
-- function 引擎.置图标(v)
--     _GGE:System_SetStateINT(0,v or 104)
-- end
--@说明 取窗口句柄
--@返回 窗口句柄
function 引擎.取窗口句柄()
    return _GGE:System_GetStateSYS()
end
-- --返回显卡可创建纹理最大尺寸
-- function 引擎.取纹理最大尺寸()
--     return _GGE:System_GetStateInt(5)
--     return 0
-- end
-- function 引擎.取纹理最大单元()
--     return _GGE:System_GetStateInt(9)
--     return 0
-- end
--@说明 向log文件写出信息(需要要引擎创建时指定LOG文件路径)
--@参数 文本
function 引擎.写日志(...)
    local arg  = {...}
    for k,v in pairs(arg) do
        arg[k] = tostring(v)
    end
    _GGE:System_Log(table.concat(arg, ", "))
end
--@说明 运行外部可执行文件或打开URL
--@参数 文件路径
--@返回 成功返回true
function 引擎.运行(v)
    return _GGE:System_Launch(v)
end

--==========================================================================
--INI
--==========================================================================
    --@说明 设置用于操作的ini文件，如果配置文件在但前目录下要在文件名前加"./"，例如：Ini_SetFile("./cfg.ini")
    --@参数 文件路径
    function 引擎.置ini(v)
        if(v:sub(1,1)~="." and v:sub(2,2) ~= ":")then v="./"..v end
        _GGE:Ini_SetFile(v)
        return 引擎
    end
    --@说明 写配置文件
    --@参数 节点名
    --@参数 配置名
    --@参数 内容
    function 引擎.写ini(section,name,value)
        _GGE:Ini_SetString(section,name,tostring(value))
    end
    --@说明 读配置文件
    --@参数 节点名
    --@参数 配置名
    function 引擎.读ini(section,name)
        if(self.已运行)then
            local 结果 = _GGE:Ini_GetString(section,name,"")
            return (结果~="" and 结果 or nil)
        end
        return nil
    end
    --最大256
    function 引擎.读配置项(f,...)
        self.置ini(f)
        return self.读ini(...)
    end
    function 引擎.写配置项(f,...)
        self.置ini(f)
        return self.写ini(...)
    end
--==========================================================================
--时间
--==========================================================================
    --@返回 游戏运行时间长
    function 引擎.取游戏时间()
        return _GGE:Timer_GetTime()
    end
    --@返回 系统时间
    function 引擎.取时间戳() --系统时间
        return _GGE:Timer_GetTick()
    end
    --@返回 一帧所用时间
    function 引擎.取帧时间()
        return _GGE:Timer_GetDelta()
    end
    --@返回 FPS
    function 引擎.取FPS()
        return _GGE:Timer_GetFPS()
    end
--==========================================================================
--随机
--==========================================================================
    -- @brief 创建一个独立的随机数生成器，以防止被其他因素干扰
    -- @return 随机数生成器ID
    function 引擎.随机创建()
        return _GGE:Random_Create()
    end
    --@参数 数值
    function 引擎.置随机种子(v,rid)
        _GGE:Random_Seed(v or os.time(),rid or 0)
    end
    --@参数 最小整数,最大整数
    --@返回 随机结果
    function 引擎.取随机整数(a,b,rid)
        return _GGE:Random_Int(a or 0,b or 100,rid or 0)
    end
    --@参数 最小小数,最大小数
    --@返回 随机结果
    function 引擎.取随机小数(a,b,rid)
        return _GGE:Random_Float(a or 0,b or 1,rid or 0)
    end
    -- @brief 创建一个独立的随机数生成器(Mersenne Twister)，以防止被其他因素干扰
    -- @return 随机数生成器ID
    function 引擎.随机创建MT()
        return _GGE:Random_CreateMt()
    end
    --@参数 数值
    function 引擎.置随机种子MT(v,rid)
        _GGE:Random_SeedMt(v or os.time(),rid or 0)
    end
    --@参数 最小整数,最大整数
    --@返回 随机结果
    function 引擎.取随机整数MT(a,b,rid)
        return _GGE:Random_IntMt(a or 0,b or 100,rid or 0)
    end
    --@参数 最小小数,最大小数
    --@返回 随机结果
    function 引擎.取随机小数MT(a,b,rid)
        return _GGE:Random_FloatMt(a or 0,b or 1,rid or 0)
    end
--==========================================================================
--渲染
--==========================================================================
    --@说明 以指定颜色清除屏幕
    --@参数 屏幕颜色
    function 引擎.渲染清除(color)
        _GGE:Graph_Clear(color or 0)
    end
    --@说明 渲染开始
    --@参数 若该纹理为渲染目标纹理，则渲染到该纹理，否则渲染到默认渲染目标|创建方法 纹理():渲染目标(...)
    function 引擎.渲染开始(texture)
        if texture and tostring(texture:取对象())=='ggeTexture' then
            return _GGE:Graph_BeginScene(texture:取指针())
        end
        return _GGE:Graph_BeginScene(0)
    end
    --@说明 渲染结束
    function 引擎.渲染结束()
        for i,v in ipairs(_渲染列表) do
            v:显示(_XY.x,_XY.y,_XY)
        end
        _GGE:Graph_EndScene()
    end

    --@参数 起点xy,终点xy,颜色(可空)
    function 引擎.画线(x1,y1,x2,y2,color)
        _GGE:Graph_RenderLine(x1,y1,x2,y2,color or 0xFFFF0000)
    end
    --@参数 起点xy,终点xy,颜色(可空)
    function 引擎.画矩形(x1,y1,x2,y2,color)
        _GGE:Graph_RenderRect(x1,y1,x2,y2,color or 0xFFFFFFFF)
    end
    function 引擎.画三角形(triple)
        _GGE:Graph_RenderTriple(triple)
    end
    function 引擎.画四边形(quad)
        _GGE:Graph_RenderQuad(quad)
    end
    --@参数 起点xy,终点xy
    function 引擎.置区域(x1,y1,width,height)
        _GGE:Graph_SetClipping(x1,y1,width,height)
    end
    --@参数
        -- @param x 中心点x坐标
        -- @param y 中心点y坐标
        -- @param dx 中心点x坐标偏移量
        -- @param dy 中心点y坐标偏移量
        -- @param rot 旋转角度(单位:弧度)
        -- @param hscale 横坐标缩放比例
        -- @param vscale 纵坐标缩放比例
        -- @note 若所有参数为0则重置为默认值
    function 引擎.置变换(x,y,dx,dy,rot,hscale,vscale)
        _GGE:Graph_SetTransform(x,y,dx,dy,rot,hscale,vscale)
    end

    -- @brief 渲染自定义图元(该函数会增加DrawCall)
    -- @param primType 图元类型
    -- @param vt 顶点数组
    -- @param primNum 图元数量
    -- @param tex 渲染图元时使用的纹理
    -- @param blend 纹理混合模式，可用"|"结合
    function 引擎.画图元(primType,vt,primNum,tex,blend)
        tex = tex and tex:取指针() or 0
        _GGE:Graph_RenderBatch(primType,vt,primNum,tex,blend or 0)
    end
    -- @brief 渲染自定义索引图元(该函数会增加DrawCall)
    -- @param primType 图元类型，不支持 PRIM_POINTS, PRIM_QUADS
    -- @param vt 顶点数组
    -- @param vertexNum 顶点数量
    -- @param indices 索引数组
    -- @param primNum 图元数量
    -- @param tex 渲染图元时使用的纹理
    -- @param blend 纹理混合模式，可用"|"结合
    -- function 引擎.Graph_RenderBatchIndices(primType,vt,vertexNum,indices,tex,blend)
    --     tex = tex and tex:取指针() or nil
    --     _GGE:Graph_RenderBatchIndices(primType,vt,vertexNum,indices,tex,blend or 0)
    -- end
    -- -- @brief 设置投影矩阵(该函数会增加DrawCall)
    -- -- @param mat 投影矩阵，为0时重置为默认投影矩阵
    -- function 引擎.Graph_SetProjectionMatrix(mat)
    --     _GGE:Graph_SetProjectionMatrix(mat)
    -- end
    -- function 引擎.Graph_GetProjectionMatrix()
    --     return _GGE:Graph_GetProjectionMatrix()
    -- end
    -- -- @brief 设置视图矩阵(该函数会增加DrawCall)
    -- -- @param mat 视图矩阵，为0时重置为默认视图矩阵
    -- function 引擎.Graph_SetViewMatrix(mat)
    --     _GGE:Graph_SetViewMatrix(mat)
    -- end
    -- function 引擎.Graph_GetViewMatrix()
    --     return _GGE:Graph_GetViewMatrix()
    -- end
    -- -- @brief 设置变换矩阵(该函数使用CPU计算顶点坐标，不会增加DrawCall)
    -- -- @param mat 变换矩阵
    -- function 引擎.Graph_SetTransformMatrix(mat)
    --     _GGE:Graph_SetTransformMatrix(mat)
    -- end
    -- function 引擎.Graph_GetTransformMatrix()
    --     return _GGE:Graph_GetTransformMatrix()
    -- end
    -- /// 屏幕截图格式
    local 截图格式 =
    {
        JPG  = 0,--IMAGE_JPG, ///<
        PNG  = 1,--IMAGE_PNG, ///<
        BMP  = 2,--IMAGE_BMP, ///<
        TGA  = 3,--IMAGE_TGA, ///<
        DXT1 = 4,--IMAGE_DXT1,///<
        DXT3 = 5,--IMAGE_DXT3,///<
        DXT5 = 6,--IMAGE_DXT5,///<
    };
    --@参数 文件路径
    function 引擎.截图(路径,格式)
        _GGE:Graph_Snapshot(路径,截图格式[格式] or 0)
    end
    function 引擎.截图到纹理(texture)--必须是渲染目标纹理
        _GGE:Graph_GetRenderTarget(texture:取指针())
    end
    function 引擎.置著色器(shader)--必须是渲染目标纹理
        _GGE:Graph_SetCurrentShader(shader:取指针())
        return self
    end
    function 引擎.取著色器()
        return _GGE:Graph_GetCurrentShader()
    end
--==========================================================================
--输入
--==========================================================================
    --@返回 x,y
    function 引擎.取鼠标坐标(类)
        if(self.已运行)then
            if 类 then
                return require("gge坐标类")(_GGE:Input_GetMousePosX(),_GGE:Input_GetMousePosY())
            end
            return _GGE:Input_GetMousePosX(),_GGE:Input_GetMousePosY()
        end
    end
    function 引擎.置鼠标坐标(x,y)
        _GGE:Input_SetMousePos(x,y)
    end
    --@返回 滚动值
    function 引擎.取鼠标滚轮()
        return _GGE:Input_GetMouseWheel()
    end
    --@返回 逻辑值
    function 引擎.是否在窗口内()
        return _GGE:Input_IsMouseOver()
    end
    --@参数 键值
    --@返回 逻辑值
    function 引擎.按键按住(v)
        return _GGE:Input_IsKeyPress(v)
    end
    --@参数 键值
    --@返回 逻辑值
    function 引擎.按键弹起(v)
        return _GGE:Input_IsKeyUp(v)
    end
    --@参数 键值
    --@返回 逻辑值
    function 引擎.按键按下(v)
        return _GGE:Input_IsKeyDown(v)
    end
    --@参数 键值
    --@返回 逻辑值
    function 引擎.鼠标按住(v)
        return _GGE:Input_IsMousePress(v)
    end
    --@参数 键值
    --@返回 逻辑值
    function 引擎.鼠标弹起(v)
        return _GGE:Input_IsMouseUp(v)
    end
    --@参数 键值
    --@返回 逻辑值
    function 引擎.鼠标按下(v)
        return _GGE:Input_IsMouseDown(v)
    end
    --@返回 键盘键值
    function 引擎.取按下键值()
        return _GGE:Input_GetKey()
    end
    --@返回 输入字符
    function 引擎.取输入字符()
        return _GGE:Input_GetChar()
    end
    function 引擎.取按键名称(k)
        return _GGE:Input_GetKeyName(k)
    end
--==========================================================================
--音效
--==========================================================================
    -- @brief 设置全局最大音量
    -- @param volume 全局最大音量，范围0～100
    function 引擎.Audio_SetMaxVolume(volume)
        _GGE:Audio_SetMaxVolume(volume)
    end
    function 引擎.Audio_GetMaxVolume()
        return _GGE:Audio_GetMaxVolume()
    end
    -- @brief 设置监听器位置
    -- @param position 监听器位置(右手坐标系)
    function 引擎.Audio_SetListenerPosition(position)
        _GGE:Audio_SetListenerPosition(position)
    end
    function 引擎.Audio_GetListenerPosition()
        return _GGE:Audio_GetListenerPosition()
    end
    -- @brief 设置监听器速度
    -- @param velocity 监听器速度
    function 引擎.Audio_SetListenerVelocity(velocity)
        _GGE:Audio_SetListenerVelocity(velocity)
    end
    function 引擎.Audio_GetListenerVelocity()
        return _GGE:Audio_GetListenerVelocity()
    end
    -- @brief 设置监听器方向
    -- @param forward 前方向，默认(0, 0, -1)
    -- @param up 上方向，默认(0, 1, 0)
    function 引擎.Audio_SetListenerOrientation(forward, up)
        _GGE:Audio_SetListenerOrientation(forward, up)
    end
    function 引擎.Audio_GetListenerOrientationForward()
        return _GGE:Audio_GetListenerOrientationForward()
    end
    function 引擎.Audio_GetListenerOrientationUp()
        return _GGE:Audio_GetListenerOrientationUp()
    end
    -- @brief 设置多普勒系数
    -- @param scale 多普勒系数，默认1，值越大影响越大
    function 引擎.Audio_SetDopplerScale(scale)
        _GGE:Audio_SetDopplerScale(scale)
    end
    function 引擎.Audio_GetDopplerScale()
        return _GGE:Audio_GetDopplerScale()
    end
    -- @brief 设置距离模型
    -- @param model 距离模型，默认 AUDIO_DISTANCE_INVERSE_CLAMPED
    function 引擎.Audio_SetDistanceModel(model)
        _GGE:Audio_SetDistanceModel(model)
    end
    function 引擎.Audio_GetDistanceModel()
        return _GGE:Audio_GetDistanceModel()
    end
--==========================================================================
--键值常量
--==========================================================================
    KEY = {}

    KEY.LBUTTON    = 0x00--鼠标左
    KEY.RBUTTON    = 0x01--鼠标右
    KEY.MBUTTON    = 0x02--鼠标中

    KEY.ESCAPE     = 0x1B--ESC
    KEY.BACKSPACE  = 0x08--退格
    KEY.TAB        = 0x09
    KEY.ENTER      = 0x0D
    KEY.SPACE      = 0x20--空格

    KEY.SHIFT      = 0x10
    KEY.CTRL       = 0x11
    KEY.ALT        = 0x12

    KEY.LWIN       = 0x5B--左WIN
    KEY.RWIN       = 0x5C--右WIN
    KEY.APPS       = 0x5D

    KEY.PAUSE      = 0x13
    KEY.CAPSLOCK   = 0x14
    KEY.NUMLOCK    = 0x90
    KEY.SCROLLLOCK = 0x91

    KEY.PGUP       = 0x21
    KEY.PGDN       = 0x22
    KEY.HOME       = 0x24
    KEY.END        = 0x23
    KEY.INSERT     = 0x2D
    KEY.DELETE     = 0x2E

    KEY.LEFT       = 0x25--左
    KEY.UP         = 0x26--上
    KEY.RIGHT      = 0x27--右
    KEY.DOWN       = 0x28--下

    KEY._0         = 0x30
    KEY._1         = 0x31
    KEY._2         = 0x32
    KEY._3         = 0x33
    KEY._4         = 0x34
    KEY._5         = 0x35
    KEY._6         = 0x36
    KEY._7         = 0x37
    KEY._8         = 0x38
    KEY._9         = 0x39

    KEY.A          = 0x41
    KEY.B          = 0x42
    KEY.C          = 0x43
    KEY.D          = 0x44
    KEY.E          = 0x45
    KEY.F          = 0x46
    KEY.G          = 0x47
    KEY.H          = 0x48
    KEY.I          = 0x49
    KEY.J          = 0x4A
    KEY.K          = 0x4B
    KEY.L          = 0x4C
    KEY.M          = 0x4D
    KEY.N          = 0x4E
    KEY.O          = 0x4F
    KEY.P          = 0x50
    KEY.Q          = 0x51
    KEY.R          = 0x52
    KEY.S          = 0x53
    KEY.T          = 0x54
    KEY.U          = 0x55
    KEY.V          = 0x56
    KEY.W          = 0x57
    KEY.X          = 0x58
    KEY.Y          = 0x59
    KEY.Z          = 0x5A

    KEY.GRAVE      = 0xC0
    KEY.MINUS      = 0xBD
    KEY.EQUALS     = 0xBB
    KEY.BACKSLASH  = 0xDC
    KEY.LBRACKET   = 0xDB
    KEY.RBRACKET   = 0xDD
    KEY.SEMICOLON  = 0xBA
    KEY.APOSTROPHE = 0xDE
    KEY.COMMA      = 0xBC
    KEY.PERIOD     = 0xBE
    KEY.SLASH      = 0xBF

    KEY.NUMPAD0    = 0x60--小键盘数字
    KEY.NUMPAD1    = 0x61
    KEY.NUMPAD2    = 0x62
    KEY.NUMPAD3    = 0x63
    KEY.NUMPAD4    = 0x64
    KEY.NUMPAD5    = 0x65
    KEY.NUMPAD6    = 0x66
    KEY.NUMPAD7    = 0x67
    KEY.NUMPAD8    = 0x68
    KEY.NUMPAD9    = 0x69

    KEY.MULTIPLY   = 0x6A
    KEY.DIVIDE     = 0x6F
    KEY.ADD        = 0x6B
    KEY.SUBTRACT   = 0x6D
    KEY.DECIMAL    = 0x6E

    KEY.F1         = 0x70
    KEY.F2         = 0x71
    KEY.F3         = 0x72
    KEY.F4         = 0x73
    KEY.F5         = 0x74
    KEY.F6         = 0x75
    KEY.F7         = 0x76
    KEY.F8         = 0x77
    KEY.F9         = 0x78
    KEY.F10        = 0x79
    KEY.F11        = 0x7A
    KEY.F12        = 0x7B
--==========================================================================
--混合常量
--==========================================================================
do
    BLEND              = {}
    BLEND.COLORMUL     = 0     --< 颜色乘
    BLEND.COLORADD     = 1     --< 颜色加
    BLEND.ALPHAMUL     = 0     --< alpha乘
    BLEND.ALPHAADD     = 2     --< alpha加
    BLEND.NOZWRITE     = 0     --< 不将顶点的Z轴写入Z缓冲
    BLEND.ZWRITE       = 4     --< 将顶点的Z轴写入Z缓冲
    BLEND.NOTEXFILTER  = 0     --< 关闭纹理过滤
    BLEND.TEXFILTER    = 8     --< 开启纹理过滤
    --BLEND.DEFAULT    = bit.bor(BLEND.COLORMUL,BLEND.ALPHAMUL,BLEND.NOZWRITE)     --< 默认混合模式
    BLEND.DEFAULT_Z    = bit.bor(BLEND.COLORMUL,BLEND.ALPHAMUL,BLEND.ZWRITE)       --< 默认开启Z轴写入混合模式
    BLEND.FORCE32BIT   = 0x7FFFFFFF

    BLEND.DEFAULT      = 0     --< 默认值
    BLEND.ZERO         = 1     --< ( 0, 0, 0, 0 )
    BLEND.ONE          = 2     --< ( 1, 1, 1, 1 )
    BLEND.SRCCOLOR     = 3     --< ( Rs, Gs, Bs, As )
    BLEND.INVSRCCOLOR  = 4     --< ( 1 - Rs, 1 - Gs, 1 - Bs, 1 - As )
    BLEND.SRCALPHA     = 5     --< ( As, As, As, As )
    BLEND.INVSRCALPHA  = 6     --< ( 1 - As, 1 - As, 1 - As, 1 - As )
    BLEND.DESTALPHA    = 7     --< ( Ad, Ad, Ad, Ad )
    BLEND.INVDESTALPHA = 8     --< ( 1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad )
    BLEND.DESTCOLOR    = 9     --< ( Rd, Gd, Bd, Ad )
    BLEND.INVDESTCOLOR = 10    --< ( 1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad )
    BLEND.SRCALPHASAT  = 11    --< ( f, f, f, 1 ); f = min( As, 1 - Ad )

    local function GenAlphaBlendModeArg( srcBlend,dstBlend )
        return bit.bor(bit.lshift(srcBlend, 28),bit.lshift(dstBlend, 24))
    end
    BLEND.Alpha_Default          = GenAlphaBlendModeArg(BLEND.SRCALPHA,BLEND.INVSRCCOLOR)
    BLEND.Alpha_ColorAdd         = GenAlphaBlendModeArg(BLEND.SRCALPHA,BLEND.INVSRCALPHA)
    BLEND.Alpha_Add              = GenAlphaBlendModeArg(BLEND.SRCCOLOR,BLEND.INVSRCALPHA)
    BLEND.Alpha_SrcAlphaAdd      = GenAlphaBlendModeArg(BLEND.SRCALPHA,BLEND.ONE)
    BLEND.Alpha_SrcColor         = GenAlphaBlendModeArg(BLEND.SRCCOLOR,BLEND.INVSRCCOLOR)
    BLEND.Alpha_SrcColorAdd      = GenAlphaBlendModeArg(BLEND.SRCCOLOR,BLEND.ONE)
    BLEND.Alpha_Invert           = GenAlphaBlendModeArg(BLEND.INVDESTCOLOR,BLEND.ZERO)
    BLEND.Alpha_SrcBright        = GenAlphaBlendModeArg(BLEND.SRCCOLOR,BLEND.SRCCOLOR)
    BLEND.Alpha_Multiply         = GenAlphaBlendModeArg(BLEND.ZERO,BLEND.SRCCOLOR)
    BLEND.Alpha_InvMultiply      = GenAlphaBlendModeArg(BLEND.ZERO,BLEND.INVSRCCOLOR)
    BLEND.Alpha_MultiplyAlpha    = GenAlphaBlendModeArg(BLEND.ZERO,BLEND.SRCALPHA)
    BLEND.Alpha_InvMultiplyAlpha = GenAlphaBlendModeArg(BLEND.ZERO,BLEND.INVSRCALPHA)
    BLEND.Alpha_DestBright       = GenAlphaBlendModeArg(BLEND.DESTCOLOR,BLEND.DESTCOLOR)
    BLEND.Alpha_InvSrcBright     = GenAlphaBlendModeArg(BLEND.INVSRCCOLOR,BLEND.INVSRCCOLOR)
    BLEND.Alpha_InvDestBright    = GenAlphaBlendModeArg(BLEND.INVDESTCOLOR,BLEND.INVDESTCOLOR)
    BLEND.Alpha_Bright           = GenAlphaBlendModeArg(BLEND.SRCALPHA,BLEND.INVSRCALPHA)
    BLEND.Alpha_Light            = GenAlphaBlendModeArg(BLEND.DESTCOLOR,BLEND.ONE)
    BLEND.Alpha_Xor              = GenAlphaBlendModeArg(BLEND.INVDESTCOLOR,BLEND.INVSRCCOLOR)
end
return setmetatable(引擎,{
    __call = function (t,v)
        return t.创建(v)
    end;
    __newindex = function (t,k,v)
        rawset(t,k,v)
        if k == "更新函数" then
            _更新函数 = v
        elseif k=="渲染函数" then
            _渲染函数 = v
        end
    end
})